package com.mxgraph.io.vdx;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import java.util.HashMap;
import java.util.List;

/**
 * This class allows get the text contained in a shape formated with tags html.<br/>
 * The properties referenced in the Text element are processed by this class.
 */
public class mxVdxTextParser {
    /**
     * Shape that contains the text.
     */
    mxVdxShape shape;

    /**
     * Master Shape of the shape.
     */
    mxMasterShape masterShape;

    /**
     * Stylesheet with the Text Style.
     */
    mxStyleSheet styleSheet;

    /**
     * Stylesheet with the default text style.
     */
    mxStyleSheet defaultStyle;

    /**
     * Last cp's IX referenced in the Text Element.
     */
    String cp = "";

    /**
     * Last pp's IX referenced in the Text Element.
     */
    String pp = "";

    /**
     * Last tp's IX referenced in the Text Element.
     */
    String tp = "";

    /**
     * Last fld's IX referenced in the Text Element.
     */
    String fld = "";

    /**
     * Creates a new instance of mxVdxTextParser.
     *
     * @param shape       Shape that contains the text.
     * @param masterShape Master Shape of the shape.
     * @param styleSheet  Stylesheet with the Text Style.
     */
    public mxVdxTextParser(mxVdxShape shape, mxMasterShape masterShape,
                           mxStyleSheet styleSheet) {
        this.shape = shape;
        this.masterShape = masterShape;
        this.styleSheet = styleSheet;
        this.defaultStyle = mxPropertiesManager.getInstance().getTextStyle();
    }

    /**
     * Returns the text contained in the shape formated with tags html.<br/>
     *
     * @return Text content in html.
     */
    public String getHtmlTextContent() {
        List<Node> child = null;
        String ret = "";
        if (shape.hasText()) {
            child = shape.getTextChildrens();
        } else if ((masterShape != null) && masterShape.hasText()) {
            child = masterShape.getTextChildrens();
        }
        boolean first = true;
        if (child != null) {
            for (Node e : child) {
                if (e.getNodeName().equals("cp")) {
                    Element elem = (Element) e;
                    cp = elem.getAttribute("IX");
                } else if (e.getNodeName().equals("tp")) {
                    Element elem = (Element) e;
                    tp = elem.getAttribute("IX");
                } else if (e.getNodeName().equals("pp")) {
                    Element elem = (Element) e;
                    pp = elem.getAttribute("IX");
                    if (first) {
                        first = false;
                    } else {
                        ret += "</p>";
                    }
                    String para = "<p>";
                    ret += getTextParagraphFormated(para);
                } else if (e.getNodeName().equals("fld")) {
                    Element elem = (Element) e;
                    fld = elem.getAttribute("IX");
                    String text = elem.getTextContent();
                    text = textToList(text, pp);
                    text = text.replaceAll("\n", "<br/>");
                    ret += getTextCharFormated(text);
                } else if (e.getNodeName().equals("#text")) {
                    String text = e.getNodeValue();
                    text = textToList(text, pp);
                    text = text.replaceAll("\n", "<br/>");
                    ret += getTextCharFormated(text);

                }
            }
        }
        String end = first ? "" : "</p>";
        ret += end;
        if (!shape.hasXForm1D()) {
            ret = mxVdxUtils.surroundedByTags(ret, "div");
            HashMap<String, Object> styleMap = new HashMap<String, Object>();
            styleMap.put("width", shape.getDimentions().getX() * 0.71 + "px");
            styleMap.put("max-width", shape.getDimentions().getX() * 0.71
                    + "px");
            ret = insertAttributes(ret, styleMap);
        }
        return ret;
    }

    /**
     * Transform plain text into a html list if the Para element referenced by
     * pp indicates it.
     *
     * @param text Text to be transformed.
     * @param pp   Reference to a Para element.
     * @return Text like a html list.
     */
    public String textToList(String text, String pp) {
        if (!pp.equals("")) {
            String bullet = getBulletValue(pp);
            if (!bullet.equals("0")) {
                String[] entries = text.split("\n");
                String ret = "";
                for (String entry : entries) {
                    ret += mxVdxUtils.surroundedByTags(entry, "li");
                }
                ret = mxVdxUtils.surroundedByTags(ret, "ul");
                HashMap<String, Object> styleMap = new HashMap<String, Object>();
                if (bullet.equals("4")) {
                    styleMap.put("list-style-type", "square");
                } else {
                    styleMap.put("list-style-type", "disc");
                }
                ret = this.insertAttributes(ret, styleMap);
                return ret;
            }
        }
        return text;
    }

    /**
     * Returns the value of the Bullet element of the shape.<br/>
     * This element may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the Bullet element.
     * @return String value of the Bullet element.
     */
    public String getBulletValue(String index) {
        String bullet = "0";
        if (shape.hasBullet(index)) {
            bullet = shape.getBullet(index);
        } else if (masterShape != null && masterShape.hasBullet(index)) {
            bullet = masterShape.getBullet(index);
        } else if (styleSheet != null && styleSheet.hasBullet(index)) {
            bullet = styleSheet.getBullet(index);
        } else if (defaultStyle != null && defaultStyle.hasBullet(index)) {
            bullet = defaultStyle.getBullet(index);
        }
        return bullet;
    }

    /**
     * Returns the paragraph formated according the properties in the last
     * Para element referenced.
     *
     * @param para Paragraph to be formated
     * @return Formated paragraph.
     */
    public String getTextParagraphFormated(String para) {
        String ret = "";
        HashMap<String, Object> styleMap = new HashMap<String, Object>();

        styleMap.put("text-align", getHorzAlign(pp));
        styleMap.put("text-indent", getIndFirst(pp));
        styleMap.put("margin-left", getIndLeft(pp));
        styleMap.put("margin-right", getIndRight(pp));
        styleMap.put("margin-top", getSpcBefore(pp) + "px");
        styleMap.put("margin-bottom", getSpcAfter(pp) + "px");
        styleMap.put("line-height", getSpcLine(pp));
        styleMap.put("direction", getTextDirection(pp));
        ret += insertAttributes(para, styleMap);
        return ret;
    }

    /**
     * Returns the direction of the text. It may be right to left or left to right.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the Flags element.
     * @return The direction of the text.
     */
    public String getTextDirection(String index) {
        String direction = "ltr";
        if (shape.hasFlags(index)) {
            direction = shape.getFlags(index);
        } else if (masterShape != null && masterShape.hasFlags(index)) {
            direction = masterShape.getFlags(index);
        } else if (styleSheet != null && styleSheet.hasFlags(index)) {
            direction = styleSheet.getFlags(index);
        } else if (defaultStyle != null && defaultStyle.hasFlags(index)) {
            direction = defaultStyle.getFlags(index);
        }
        if (direction.equals("0")) {
            direction = "ltr";
        } else if (direction.equals("1")) {
            direction = "rtl";
        }
        return direction;
    }

    /**
     * Returns the space between lines in a paragraph.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the SpLine element.
     * @return The space between lines n pixels.
     */
    public String getSpcLine(String index) {
        String ret = "0";
        boolean isPercent = false;
        double space = 0;
        if (shape.hasSpLine(index)) {
            space = shape.getSpLine(index);
        } else if (masterShape != null && masterShape.hasSpLine(index)) {
            space = masterShape.getSpLine(index);
        } else if (styleSheet != null && styleSheet.hasSpLine(index)) {
            space = styleSheet.getSpLine(index);
        } else if (defaultStyle != null && defaultStyle.hasSpLine(index)) {
            space = defaultStyle.getSpLine(index);
        }
        if (space > 0) {
            space = space * mxVdxUtils.conversionFactor();
        } else if (space == 0) {
            space = 100;
            isPercent = true;
        } else {
            space = Math.abs(space) * 100;
            isPercent = true;
        }
        ret = String.valueOf(space);
        ret += isPercent ? "%" : "px";
        return ret;
    }

    /**
     * Returns the space before a paragraph.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the SpBefore element.
     * @return The space before the paragraph in pixels.
     */
    public String getSpcBefore(String index) {
        String ret = "0";

        if (shape.hasSpBefore(index)) {
            ret = shape.getSpBefore(index);
        } else if (masterShape != null && masterShape.hasSpBefore(index)) {
            ret = masterShape.getSpBefore(index);
        } else if (styleSheet != null && styleSheet.hasSpBefore(index)) {
            ret = styleSheet.getSpBefore(index);
        } else if (defaultStyle != null && defaultStyle.hasSpBefore(index)) {
            ret = defaultStyle.getSpBefore(index);
        }

        return ret;
    }

    /**
     * Returns the space after a paragraph.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the SpAfter element.
     * @return The space after the paragraph in pixels.
     */
    public String getSpcAfter(String index) {
        String ret = "0";

        if (shape.hasSpAfter(index)) {
            ret = shape.getSpAfter(index);
        } else if (masterShape != null && masterShape.hasSpAfter(index)) {
            ret = masterShape.getSpAfter(index);
        } else if (styleSheet != null && styleSheet.hasSpAfter(index)) {
            ret = styleSheet.getSpAfter(index);
        } else if (defaultStyle != null && defaultStyle.hasSpAfter(index)) {
            ret = defaultStyle.getSpAfter(index);
        }

        return ret;
    }

    /**
     * Returns the indent to left in a paragraph.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the IndLeft element.
     * @return The indent to left in a paragraph in pixels.
     */
    public String getIndLeft(String index) {
        String ret = "0";

        if (shape.hasIndentLeft(index)) {
            ret = shape.getIndentLeft(index);
        } else if (masterShape != null && masterShape.hasIndentLeft(index)) {
            ret = masterShape.getIndentLeft(index);
        } else if (styleSheet != null && styleSheet.hasIndentLeft(index)) {
            ret = styleSheet.getIndentLeft(index);
        } else if (defaultStyle != null && defaultStyle.hasIndentLeft(index)) {
            ret = defaultStyle.getIndentLeft(index);
        }

        return ret;
    }

    /**
     * Returns the indent to right in a paragraph.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the IndRight element.
     * @return The indent to right in a paragraph in pixels.
     */
    public String getIndRight(String index) {
        String ret = "0";

        if (shape.hasIndentRight(index)) {
            ret = shape.getIndentRight(index);
        } else if (masterShape != null && masterShape.hasIndentRight(index)) {
            ret = masterShape.getIndentRight(index);
        } else if (styleSheet != null && styleSheet.hasIndentRight(index)) {
            ret = styleSheet.getIndentRight(index);
        } else if (defaultStyle != null && defaultStyle.hasIndentRight(index)) {
            ret = defaultStyle.getIndentRight(index);
        }

        return ret;
    }

    /**
     * Returns the indent of the first line in a paragraph.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the IndFirst element.
     * @return The indent of the first line in a paragraph in pixels.
     */
    public String getIndFirst(String index) {
        String ret = "0";

        if (shape.hasIndentFirst(index)) {
            ret = shape.getIndentFirst(index);
        } else if (masterShape != null && masterShape.hasIndentFirst(index)) {
            ret = masterShape.getIndentFirst(index);
        } else if (styleSheet != null && styleSheet.hasIndentFirst(index)) {
            ret = styleSheet.getIndentFirst(index);
        } else if (defaultStyle != null && defaultStyle.hasIndentFirst(index)) {
            ret = defaultStyle.getIndentFirst(index);
        }
        return ret;
    }

    /**
     * Return the value of the horizontal align.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Para element that contains the HorzAlign element.
     * @return The value of the horizontal align in a paragraph.
     */
    public String getHorzAlign(String index) {
        String ret = "center";
        int align = 0;
        if (shape.hasHorizontalAlign(index)) {
            align = shape.getHorizontalAlign(index);
        } else if (masterShape != null && masterShape.hasHorizontalAlign(index)) {
            align = masterShape.getHorizontalAlign(index);
        } else if (styleSheet != null && styleSheet.hasHorizontalAlign(index)) {
            align = styleSheet.getHorizontalAlign(index);
        } else if (defaultStyle != null && defaultStyle.hasHorizontalAlign(index)) {
            align = defaultStyle.getHorizontalAlign(index);
        }
        switch (align) {
            case 0:
                ret = "left";
                break;
            case 1:
                ret = "center";
                break;
            case 2:
                ret = "right";
                break;
            case 3:
                ret = "justify";
        }
        return ret;
    }

    /**
     * Inserts the style attributes contained in attr into the text.<br/>
     * The text must be surrounded by tags html.
     *
     * @param text Text where the attributes must be inserted.
     * @param attr Map with the attributes.
     * @return Text with the attributes applied like style.
     */
    public String insertAttributes(String text, HashMap<String, Object> attr) {
        int i = text.indexOf(">");
        String tail = text.substring(i);
        String head = text.substring(0, i);
        String style = " style=\"" + mxVdxUtils.getStyleString(attr, ":")
                + "\"";
        return head + style + tail;
    }

    /**
     * Returns the text formated according the properties in the last
     * Char element referenced.
     *
     * @param text Text to be formated
     * @return Formated text.
     */
    public String getTextCharFormated(String text) {
        String ret = "";
        String color = "color:" + this.getTextColor(cp) + ";";
        String size = "font-size:" + this.getTextSize(cp) + "px;";
        String font = "font-family:" + this.getTextFont(cp) + ";";
        String direction = "direction:" + this.getCharDirection(cp) + ";";
        String space = "letter-spacing:" + this.getCharSpace(cp) + "px;";
        int pos = this.getPos(cp);
        boolean bold = this.isBold(cp);
        boolean italic = this.isItalic(cp);
        boolean underline = this.isUnderline(cp);
        boolean strike = this.isStrikeThru(cp);
        boolean smallCap = this.isSmallCaps(cp);
        int tCase = this.getCase(cp);

        if (tCase == 1) {
            text = text.toUpperCase();
        } else if (tCase == 2) {
            text = mxVdxUtils.toInitialCapital(text);
        }
        if (smallCap) {
            text = mxVdxUtils.toSmallCaps(text, this.getTextSize(cp));
        }

        if (pos == 1) {
            text = mxVdxUtils.surroundedByTags(text, "sup");
        } else if (pos == 2) {
            text = mxVdxUtils.surroundedByTags(text, "sub");
        }
        if (bold) {
            text = mxVdxUtils.surroundedByTags(text, "b");
        }
        if (italic) {
            text = mxVdxUtils.surroundedByTags(text, "i");
        }
        if (underline) {
            text = mxVdxUtils.surroundedByTags(text, "u");
        }
        if (strike) {
            text = mxVdxUtils.surroundedByTags(text, "s");
        }

        ret += "<font style=\"" + size + font + color + direction + space
                + "\">" + text + "</font>";
        return ret;
    }

    /**
     * Returns the space between characters.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the LetterSpace element.
     * @return String representation of the space between characters in pixels.
     */
    public String getCharSpace(String index) {
        String space = "0";
        if (shape.hasLetterSpace(index)) {
            space = shape.getLetterSpace(index);
        } else if (masterShape != null && masterShape.hasLetterSpace(index)) {
            space = masterShape.getLetterSpace(index);
        } else if (styleSheet != null && styleSheet.hasLetterSpace(index)) {
            space = styleSheet.getLetterSpace(index);
        } else if (defaultStyle != null && defaultStyle.hasLetterSpace(index)) {
            space = defaultStyle.getLetterSpace(index);
        }
        return space;
    }

    /**
     * Returns the direction of the text. It may be right to left or left to right.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the RTLText element.
     * @return Direction of the text.
     */
    public String getCharDirection(String index) {
        String direction = "ltr";
        if (shape.hasRTLText(index)) {
            direction = shape.getRTLText(index);
        } else if (masterShape != null && masterShape.hasRTLText(index)) {
            direction = masterShape.getRTLText(index);
        } else if (styleSheet != null && styleSheet.hasRTLText(index)) {
            direction = styleSheet.getRTLText(index);
        } else if (defaultStyle != null && defaultStyle.hasRTLText(index)) {
            direction = defaultStyle.getRTLText(index);
        }
        if (direction.equals("0")) {
            direction = "ltr";
        } else if (direction.equals("1")) {
            direction = "rtl";
        }
        return direction;
    }

    /**
     * Returns the value of the case property.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Case element.
     * @return Value of the case property.
     */
    public int getCase(String index) {
        int tCase = 0;
        if (shape.hasTextStyle(index)) {
            tCase = shape.getTextCase(index);
        } else if (masterShape != null && masterShape.hasTextCase(index)) {
            tCase = masterShape.getTextCase(index);
        } else if (styleSheet != null && styleSheet.hasTextCase(index)) {
            tCase = styleSheet.getTextCase(index);
        } else if (defaultStyle != null && defaultStyle.hasTextCase(index)) {
            tCase = defaultStyle.getTextCase(index);
        }
        return tCase;
    }

    /**
     * Returns the Position of the text(If is superscript, subscript or normal text).<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Pos element.
     * @return Value of the Pos element.
     */
    public int getPos(String index) {
        int pos = 0;
        if (shape.hasTextPos(index)) {
            pos = shape.getTextPos(index);
        } else if (masterShape != null && masterShape.hasTextPos(index)) {
            pos = masterShape.getTextPos(index);
        } else if (styleSheet != null && styleSheet.hasTextPos(index)) {
            pos = styleSheet.getTextPos(index);
        } else if (defaultStyle != null && defaultStyle.hasTextPos(index)) {
            pos = defaultStyle.getTextPos(index);
        }
        return pos;
    }

    /**
     * Checks if the style property of the Char element of index = 'index'
     * indicates bold.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Style element.
     * @return Returns <code>true</code> if the style property of the Char element of
     *         index = 'index' indicates bold.
     */
    public boolean isBold(String index) {
        boolean isBold = false;
        String style = "";
        if (shape.hasTextStyle(index)) {
            style = shape.getTextStyle(index);
        } else if (masterShape != null && masterShape.hasTextStyle(index)) {
            style = masterShape.getTextStyle(index);
        } else if (styleSheet != null && styleSheet.hasTextStyle(index)) {
            style = styleSheet.getTextStyle(index);
        } else if (defaultStyle != null && defaultStyle.hasTextStyle(index)) {
            style = defaultStyle.getTextStyle(index);
        }
        if (!style.equals("")) {
            int value = Integer.parseInt(style);
            isBold = ((value & 1) == 1);
        }
        return isBold;
    }

    /**
     * Checks if the style property of the Char element of index = 'index'
     * indicates italic.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Style element.
     * @return Returns <code>true</code> if the style property of the Char element of
     *         index = 'index' indicates italic.
     */
    public boolean isItalic(String index) {
        boolean isItalic = false;
        String style = "";
        if (shape.hasTextStyle(index)) {
            style = shape.getTextStyle(index);
        } else if (masterShape != null && masterShape.hasTextStyle(index)) {
            style = masterShape.getTextStyle(index);
        } else if (styleSheet != null && styleSheet.hasTextStyle(index)) {
            style = styleSheet.getTextStyle(index);
        } else if (defaultStyle != null && defaultStyle.hasTextStyle(index)) {
            style = defaultStyle.getTextStyle(index);
        }
        if (!style.equals("")) {
            int value = Integer.parseInt(style);
            isItalic = ((value & 2) == 2);
        }
        return isItalic;
    }

    /**
     * Checks if the style property of the Char element of index = 'index'
     * indicates underline.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Style element.
     * @return Returns <code>true</code> if the style property of the Char element of
     *         index = 'index' indicates underline.
     */
    public boolean isUnderline(String index) {
        boolean isUnderline = false;
        String style = "";
        if (shape.hasTextStyle(index)) {
            style = shape.getTextStyle(index);
        } else if (masterShape != null && masterShape.hasTextStyle(index)) {
            style = masterShape.getTextStyle(index);
        } else if (styleSheet != null && styleSheet.hasTextStyle(index)) {
            style = styleSheet.getTextStyle(index);
        } else if (defaultStyle != null && defaultStyle.hasTextStyle(index)) {
            style = defaultStyle.getTextStyle(index);
        }
        if (!style.equals("")) {
            int value = Integer.parseInt(style);
            isUnderline = ((value & 4) == 4);
        }
        return isUnderline;
    }

    /**
     * Checks if the style property of the Char element of index = 'index'
     * indicates small caps.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Style element.
     * @return Returns <code>true</code> if the style property of the Char element of
     *         index = 'index' indicates small caps.
     */
    public boolean isSmallCaps(String index) {
        boolean isSmallCaps = false;
        String style = "";
        if (shape.hasTextStyle(index)) {
            style = shape.getTextStyle(index);
        } else if (masterShape != null && masterShape.hasTextStyle(index)) {
            style = masterShape.getTextStyle(index);
        } else if (styleSheet != null && styleSheet.hasTextStyle(index)) {
            style = styleSheet.getTextStyle(index);
        } else if (defaultStyle != null && defaultStyle.hasTextStyle(index)) {
            style = defaultStyle.getTextStyle(index);
        }
        if (!style.equals("")) {
            int value = Integer.parseInt(style);
            isSmallCaps = ((value & 8) == 8);
        }
        return isSmallCaps;
    }

    /**
     * Checks if the strikethru property of the Char element of index = 'index'
     * indicates true.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the StrikeThru element.
     * @return Returns <code>true</code> if the strikethru property of the Char
     *         element of index = 'index' indicates true.
     */
    public boolean isStrikeThru(String index) {
        boolean isStrikeThru = false;
        if (shape.hasTextStrike(index)) {
            isStrikeThru = shape.getTextStrike(index);
        } else if (masterShape != null && masterShape.hasTextStrike(index)) {
            isStrikeThru = masterShape.getTextStrike(index);
        } else if (styleSheet != null && styleSheet.hasTextStrike(index)) {
            isStrikeThru = styleSheet.getTextStrike(index);
        } else if (defaultStyle != null && defaultStyle.hasTextStrike(index)) {
            isStrikeThru = defaultStyle.getTextStrike(index);
        }
        return isStrikeThru;
    }

    /**
     * Returns the actual font defined by the Char element referenced in cp.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Font element.
     * @return Returns the name of the font.
     */
    public String getTextFont(String index) {
        String font = "";
        if (shape.hasTextFont(index)) {
            font = shape.getTextFont(index);
        } else if (masterShape != null && masterShape.hasTextFont(index)) {
            font = masterShape.getTextFont(index);
        } else if (styleSheet != null && styleSheet.hasTextFont(index)) {
            font = styleSheet.getTextFont(index);
        } else if (defaultStyle != null && defaultStyle.hasTextFont(index)) {
            font = defaultStyle.getTextFont(index);
        }
        return font;
    }

    /**
     * Returns the actual text size defined by the Char element referenced in cp.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Size element.
     * @return Returns the size of the font in pixels.
     */
    private String getTextSize(String index) {
        String size = "12";
        if (shape.hasTextSize(index)) {
            size = shape.getTextSize(index);
        } else if (masterShape != null && masterShape.hasTextSize(index)) {
            size = masterShape.getTextSize(index);
        } else if (styleSheet != null && styleSheet.hasTextSize(index)) {
            size = styleSheet.getTextSize(index);
        } else if (defaultStyle != null && defaultStyle.hasTextSize(index)) {
            size = defaultStyle.getTextSize(index);
        }
        double s = Double.valueOf(size) * 0.71;
        return String.valueOf(s);
    }

    /**
     * Returns the actual color defined by the Char element referenced in cp.<br/>
     * This property may to be founded in the shape, master shape, stylesheet or
     * default stylesheet.
     *
     * @param index Index of the Char element that contains the Color element.
     * @return Returns the color of the text in hexadecimal.
     */
	private String getTextColor(String index)
	{
		String color = "#000000";
		if (shape.hasTextColor(index))
		{
			color = shape.getTextColor(index);
		}
		else if (masterShape != null && masterShape.hasTextColor(index))
		{
			color = masterShape.getTextColor(index);
		}
		else if (styleSheet != null && styleSheet.hasTextColor(index))
		{
			color = styleSheet.getTextColor(index);
		}
		else if (defaultStyle != null && defaultStyle.hasTextColor(index))
		{
			color = defaultStyle.getTextColor(index);
		}
		return color;
	}
}
